#lang racket

;; By Spencer Hale

(require "Helper.scm")
(require "Output.scm")

(provide rowBox colBox)

(define rowBox ;
  (lambda (possvec rowpos colpos val)
    (let ((boxrow (* 3(quotient rowpos 3)))) ; boxrow is the top row of the current box
      (cond ((and (< 0 (vector-count (rowHasPoss? val)(vector-drop (vector-drop-right (vector-ref possvec rowpos) (- 6 colpos)) colpos))) ;if there is at least one position in the current row of the box that has the value set as possible and..
                  (equal? 0 (+ (vector-count (rowHasPoss? val) (vector-drop (vector-drop-right (vector-ref possvec (+ (modulo (+ rowpos 1) 3) boxrow)) (- 6 colpos)) colpos)) ; no positions in the other two rows of the box have the value set as possible
                               (vector-count (rowHasPoss? val) (vector-drop (vector-drop-right (vector-ref possvec (+ (modulo (+ rowpos 2) 3) boxrow)) (- 6 colpos)) colpos)))))
             (setRowSegmentTaken possvec rowpos colpos val 0)))
             ;executed under cond
      (if (not (equal? val 9)) 
          (rowBox possvec rowpos colpos (+ val 1)) ;solve for next value on same box
          (if (not (equal? colpos 6))
              (rowBox possvec rowpos (+ colpos 3) 1) ; solve for next box on same row
              (if (not (equal? rowpos 8))
                  (rowBox possvec (+ rowpos 1) 0 1) ; solve for next row
                  #t)))))) ;return true if all values have been tested for all rows of all boxes

(define setRowSegmentTaken ;removes possibility of value for all positions in the row not in the current box.
  (lambda (possvec row boxCol val count) ;boxCol is the column at the beginning of the box, count is the increment of columns
    (cond ((not (> count 8))
           (if (equal? count boxCol); when count hits boxCol, skip over the box positions in the row
               (setRowSegmentTaken possvec row boxCol val (+ count 3))
               (and (vector-set! (vector-ref (vector-ref possvec row) count) (- val 1) #f) ; set the value to not possible for the position
                    (setRowSegmentTaken possvec row boxCol val (+ count 1))))))))

(define colBox
  (lambda (possvec rowpos colpos val)
    (let ((boxcol (* 3(quotient colpos 3))))
      (cond ((and (< 0 (vector-count (colHasPoss? val colpos) (vector-drop (vector-drop-right possvec (- 6 rowpos)) rowpos))) ;if the current column of the row has at least one position where the value is possible and
                  (equal? 0 (+ (vector-count (colHasPoss? val (+ (modulo (+ colpos 1) 3) boxcol)) (vector-drop (vector-drop-right possvec (- 6 rowpos)) rowpos)) ; the other two columns do not have any positions where the value is possible
                               (vector-count (colHasPoss? val (+ (modulo (+ colpos 2) 3) boxcol)) (vector-drop (vector-drop-right possvec (- 6 rowpos)) rowpos)))))
             (setColSegmentTaken possvec rowpos colpos val 0))) ;executed under cond))
      (if (not (equal? val 9)) 
          (colBox possvec rowpos colpos (+ val 1)); solve for next value
          (if (not (equal? rowpos 6))
              (colBox possvec (+ rowpos 3) colpos 1) ; solve for next box in the column
              (if (not (equal? colpos 8)) 
                  (colBox possvec 0 (+ colpos 1) 1) ; solve for next column
                  #t)))))); return true if all values have been tested for all columns of all boxes

(define setColSegmentTaken ; removes possibility of value for all positions in the column not in the current box
  (lambda (possvec boxRow col val count) ;boxRow is the row at the beginning of the box, count is the increment of rows
    (cond ((not (> count 8))
        (if (equal? count boxRow) ;when count hits boxRow, skip over box positions in the column
            (setColSegmentTaken possvec boxRow col val (+ count 3))
            (and (vector-set! (vector-ref (vector-ref possvec count) col) (- val 1) #f) ;set the value to not possible for the position
                 (setColSegmentTaken possvec boxRow col val (+ count 1)))
            )))))